package cn.szv5.register.server;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 应用模块名称<p> 心跳测量计数器<p> Copyright: Copyright (C) 2022 , Inc. All rights reserved. <p> Company: 阿飞工作室<p>
 *
 * @author Carl
 * @since 2022/2/26 21:30
 */
public class HeartbeatCounter {
    private static HeartbeatCounter instance = new HeartbeatCounter();

    // 最近一分钟的心跳次数
    private AtomicLong latestMinuteHeartbeatRate = new AtomicLong(0L);
    //    private LongAdder latestMinuteHeartbeatRate = new LongAdder();

    // 最近一分钟的时间戳
    private long latestMinuteTimestamp = System.currentTimeMillis();

    private HeartbeatCounter() {
        Daemon daemon = new Daemon();
        daemon.setDaemon(true);
        daemon.start();
    }

    public static HeartbeatCounter getInstance() {
        return instance;
    }

    /**
     * 增加一次最近一分钟的心跳次数
     */
    public synchronized void increment() {
        latestMinuteHeartbeatRate.incrementAndGet();
        //        latestMinuteHeartbeatRate.increment();
    }

    /**
     * 获取最近一分钟的心跳次数
     *
     * @return
     */
    public synchronized long get() {
        //        return latestMinuteHeartbeatRate.get();
        return latestMinuteHeartbeatRate.longValue();
    }

    private class Daemon extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    long currentTime = System.currentTimeMillis();
                    if (currentTime - latestMinuteTimestamp > 60 * 1000) {
                        //                        latestMinuteHeartbeatRate.set(0L);
                        //                        latestMinuteHeartbeatRate.reset();
                        //                        latestMinuteHeartbeatRate = new AtomicLong(0);
                        //                        latestMinuteHeartbeatRate = new LongAdder();
                        while (true) {
                            long expectedValue = latestMinuteHeartbeatRate.get();
                            if (latestMinuteHeartbeatRate.compareAndSet(expectedValue, 0L)) {
                                break;
                            }
                        }
                        latestMinuteTimestamp = System.currentTimeMillis();
                    }
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
